<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\Common\Robot\Robot;
use App\CustHub\Amqp\Producers\SyncTaskProducers;
use App\CustHub\Constants\SyncTaskStatusConstants;
use App\CustHub\Constants\SyncTaskTypeConstants;
use App\CustHub\Dto\SyncTaskDto;
use App\CustHub\Mapper\ChCorpMapper;
use App\CustHub\Mapper\ChEmployeeMapper;
use App\CustHub\Mapper\ChRobotMapper;
use App\CustHub\Mapper\ChSyncTaskMapper;
use App\CustHub\Model\ChEmployee;
use App\CustHub\Model\ChRobot;
use App\CustHub\Model\ChSyncTask;
use App\Robot\Service\RobotApiService;
use Carbon\Carbon;
use Hyperf\Amqp\Producer;
use Hyperf\Di\Annotation\Inject;
use Mine\Abstracts\AbstractService;
use Mine\Exception\NormalStatusException;
use function Hyperf\Collection\collect;

class ChEmployeeService extends AbstractService
{

    public $mapper;

    #[Inject]
    protected ChSyncTaskMapper $syncTaskMapper;

    #[Inject]
    protected ChRobotMapper $robotMapper;

    #[Inject]
    protected ChCorpMapper $corpMapper;


    public function __construct(ChEmployeeMapper $mapper)
    {
        $this->mapper = $mapper;
    }

    public function getEmployeeList(array $params): array
    {
        $pageSize = $params['page_size'] ?? 10;
        $keyword = $params['keyword'] ?? '';
        $corpInfo = $this->corpMapper->findById($params['corp_id']);
        $p = ChEmployee::query()
            ->select(['id','nickname','real_name','avatar_url','corp_name','user_id'])
            ->where('main_uid',$params['main_uid'])
            ->where('corp_id',(string)$corpInfo->corp_id)
            ->when($keyword,function ($query) use ($keyword){
                $query->where('nickname','like','%'.$keyword.'%')->orWhere('real_name','like','%'.$keyword.'%');
            })
            ->paginate((int)$pageSize);
        return $this->mapper->setPaginate($p);
    }

    public function sync(array $params)
    {
        $corpInfo = $this->corpMapper->findById($params['corp_id']);
        $this->addSyncTask($params['main_uid'],$corpInfo->corp_id);
        return true;
    }

    public function addSyncTask($mainUid,$corpId): bool
    {
        $type = SyncTaskTypeConstants::EMPLOYEE;

        $robotInfo = ChRobot::query()
            ->where('main_uid',$mainUid)
            ->where('corp_wxid',$corpId)
            ->where('login_status',1)
            ->first();
        if(empty($robotInfo)){
            throw new NormalStatusException('请选登录企微号');
        }
        $robotId = $robotInfo->id;
        //检查是否存在进行中的任务
        if($this->syncTaskMapper->checkIsTaskInProgress($robotId,$type)){
            throw new NormalStatusException('同步中，请稍后再试');
        }

        $currentSeq = $this->syncTaskMapper->getLatestCurrentSeq($robotId,$type);
        empty($currentSeq) && $currentSeq = '';

        $syncTaskData = [
            'uid' => $robotInfo['uid'],
            'main_uid' => $robotInfo['main_uid'],
            'corp_id' => $robotInfo['corp_id'],
            'robot_id' => $robotInfo['id'],
            'type' => $type,
        ];

        $syncTaskId = $this->syncTaskMapper->save($syncTaskData);

        return container()->get(Producer::class)->produce(new SyncTaskProducers(new SyncTaskDto(
            taskId: $syncTaskId,
            type: $type,
            className: ChEmployeeService::class,
            method: 'batchSyncEmployee',
            currentSeq: $currentSeq
        )));
    }

    public function batchSyncEmployee(ChSyncTask $taskInfo, $currentSeq = '')
    {
        $robotId = $taskInfo->robot_id;
        $robotInfo = $this->robotMapper->findById($robotId);

        if(empty($robotInfo) || !$robotInfo->login_status){
            $this->updateSyncTask($taskInfo->id, $currentSeq);
            return;
        }

        $robotApiService = make(Robot::class, [$robotInfo->server_id, $robotInfo->uuid])->gateway();

        $data = $robotApiService->getEmployeeList($currentSeq);
        if($data !== false){
            $contactList = $data['contact_list'];
            if(!empty($contactList)){
                $userIdList = collect($contactList)->filter(function ($item) {
                    return $item['user_id'] !== 0;
                })->pluck('user_id')->toArray();
                $detail = $robotApiService->getEmployeeDetail($userIdList);
                if($detail !== false && !empty($detail['contact_list'])){
                    $detailList = $detail['contact_list'];
                    $saveData = [];
                    foreach ($detailList as $k=>$item){
                        $arr = $item;
                        $arr['main_uid'] = $robotInfo->main_uid;
                        $arr['uid'] = $robotInfo->uid;
                        $arr['corp_name'] = $robotInfo->corp_name;
                        $arr['nickname'] = $item['nickname'];
                        $arr['alias'] = $item['alias'];
                        $arr['real_name'] = $item['real_name'];
                        $arr['job'] = $item['job'];
                        $arr['created_at'] = Carbon::now();
                        $arr['updated_at'] = Carbon::now();
                        $this->mapper->filterExecuteAttributes($arr);
                        $saveData[] = $arr;
                    }
                    ChEmployee::upsert(
                        $saveData,
                        ['main_uid','corp_id', 'user_id']
                    );
                }
            }
            $currentSeq = $data['current_version'];
            if($data['has_more']){
                $this->batchSyncEmployee($taskInfo, $currentSeq);
            }
        }

        $this->updateSyncTask($taskInfo->id, $currentSeq);
    }

    private function updateSyncTask(int $taskId, mixed $currentSeq): void
    {
        $this->syncTaskMapper->update($taskId, [
            'extra' => ['current_seq' => $currentSeq],
            'end_time' => time(),
            'status' => SyncTaskStatusConstants::SUCCESS
        ]);
    }
}